package com.xianwan.util;

import eu.bitwalker.useragentutils.UserAgent;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.nutz.lang.Encoding;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;


/**
 * Created on 2017/11/19
 *
 * @author Jianghao(howechiang @ gmail.com)
 */
public class Util {

    protected static final Log log = Logs.get();

    /**
     * 手机号码转手机邮箱
     *
     * @param phone
     * @return
     */
    public static String phone2Email(String phone) {

        String number = Strings.isMobile(phone) ? phone.substring(0, 3) : "";

        switch (number) {
            case "134":
                return phone + "@139.com";
            case "135":
                return phone + "@139.com";
            case "136":
                return phone + "@139.com";
            case "137":
                return phone + "@139.com";
            case "138":
                return phone + "@139.com";
            case "139":
                return phone + "@139.com";
            case "150":
                return phone + "@139.com";
            case "151":
                return phone + "@139.com";
            case "152":
                return phone + "@139.com";
            case "157":
                return phone + "@139.com";
            case "158":
                return phone + "@139.com";
            case "159":
                return phone + "@139.com";
            case "182":
                return phone + "@139.com";
            case "183":
                return phone + "@139.com";
            case "184":
                return phone + "@139.com";
            case "187":
                return phone + "@139.com";
            case "178":
                return phone + "@139.com";
            case "188":
                return phone + "@139.com";
            case "147":
                return phone + "@139.com";
            case "130":
                return phone + "@wo.cn";
            case "131":
                return phone + "@wo.cn";
            case "132":
                return phone + "@wo.cn";
            case "145":
                return phone + "@wo.cn";
            case "155":
                return phone + "@wo.cn";
            case "156":
                return phone + "@wo.cn";
            case "176":
                return phone + "@wo.cn";
            case "185":
                return phone + "@wo.cn";
            case "186":
                return phone + "@wo.cn";
            case "133":
                return phone + "@189.cn";
            case "153":
                return phone + "@189.cn";
            case "177":
                return phone + "@189.cn";
            case "180":
                return phone + "@189.cn";
            case "181":
                return phone + "@189.cn";
            case "189":
                return phone + "@189.cn";
            default:
                return null;
        }
    }

    /**
     * 地球半径
     */
    private static final double EARTH_RADIUS = 6378137;

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 根据两点间经纬度坐标（double值），计算两点间距离，单位为米
     *
     * @param lng1
     * @param lat1
     * @param lng2
     * @param lat2
     * @return
     */
    public static double getDistance(double lng1, double lat1, double lng2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    /**
     * 取Json字段值
     *
     * @param jsonStr   JSON
     * @param field     取值字段
     * @param tailField 后一个字段 取值字段为结束字段填"}"
     * @return
     */
    public static String getValueFromJson(String jsonStr, String field,
                                          String tailField) {
        if (Strings.isBlank(jsonStr.trim())
                || Strings.isBlank(field.trim())
                || Strings.isBlank(tailField.trim())) {
            return null;
        } else {
            jsonStr = jsonStr.replaceAll("\"", "").trim();
            return Strings.removeFirst(jsonStr.substring(
                    jsonStr.indexOf(field) + field.length() + 1,
                    jsonStr.indexOf(tailField)).replaceAll(",", ""), ':').trim();
        }
    }

    public static Map<String, Object> buildNiceue(String error) {
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> resp = new HashMap<>();
        if (Lang.isEmpty(error)) {
            map.put("ok", "");
            resp.put("data", map);
            return resp;
        } else {
            map.put("error", error);
            resp.put("data", map);
            return resp;
        }
    }

    /**
     * URL转解码
     */
    public static class Url {

        /**
         * 加密
         *
         * @param s
         * @return
         */
        public static String encode(String s) {

            if (Strings.isBlank(s)) {
                log.error("s加密对象为空");
                return "";
            } else {
                try {
                    return URLEncoder.encode(s, Encoding.UTF8);
                } catch (UnsupportedEncodingException e) {
                    log.error(e.getMessage());
                    return "";
                }
            }
        }

        /**
         * 解密
         *
         * @param s
         * @return
         */
        public static String decode(String s) {

            if (Strings.isBlank(s)) {
                log.error("s加密对象为空");
                return "";
            } else {
                try {
                    return URLDecoder.decode(s, Encoding.UTF8);
                } catch (UnsupportedEncodingException e) {
                    log.error(e.getMessage());
                    return "";
                }
            }
        }
    }

    /**
     * BASE64加解密
     */
    public static class Base64 {

        /**
         * 加密
         *
         * @param s
         * @return
         */
        public static String encode(String s) {

            if (Strings.isBlank(s)) {
                log.error("s加密对象为空");
                return "";
            } else {
                return org.nutz.repo.Base64.encodeToString(s.getBytes(Encoding.CHARSET_UTF8), true);
            }
        }

        /**
         * 解密
         *
         * @param s
         * @return
         */
        public static String decode(String s) {
            if (Strings.isBlank(s)) {
                log.error("s解密对象为空");
                return "";
            } else {
                return new String(org.nutz.repo.Base64.decode(s));
            }
        }
    }

    /**
     * 取 User-Agent
     *
     * @param request
     * @return
     */
    public static String getAgent(HttpServletRequest request) {

        if (!Lang.isEmpty(request)) {
            UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
            return "操作系统版本（" + userAgent.getOperatingSystem() + "）；浏览器版本（" + userAgent.getBrowser() + "-" + userAgent.getBrowserVersion() + "）";
        } else {
            log.error("request为空");
            return "";
        }
    }

    /**
     * Map排序
     *
     * @param params 待排序对象
     * @param order  排序后的对象
     * @return
     */
    public static Map<String, Object> sorting(Map<String, Object> params, String order) {

        if (Lang.isEmpty(params)) {
            log.error("params参数为空");
            return null;
        } else {
            Map<String, Object> map = new LinkedHashMap<>();
            if (Strings.equalsIgnoreCase(order, "desc")) {
                params.entrySet().stream()
                        .sorted(Map.Entry.<String, Object>comparingByKey().reversed())
                        .forEachOrdered(x -> map.put(x.getKey(), x.getValue()));
            } else {
                params.entrySet().stream()
                        .sorted(Map.Entry.comparingByKey())
                        .forEachOrdered(x -> map.put(x.getKey(), x.getValue()));
            }
            return map;
        }
    }

    /**
     * 判断数字是否存在数组
     *
     * @param array
     * @param val
     * @return
     */
    public static Boolean checkArrayExists(Integer[] array, Integer val) {

        if (Lang.isEmpty(array)) {
            log.error("array为空");
            return false;
        } else if (Lang.isEmpty(val)) {
            log.error("val为空");
            return false;
        } else {
            for (int a : Arrays.asList(array)) {
                if (Lang.equals(a, val)) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 判断字符串是否存在数组
     *
     * @param array
     * @param val
     * @return
     */
    public static Boolean checkArrayExists(String[] array, String val) {

        if (Lang.isEmpty(array)) {
            log.error("array为空");
            return false;
        } else if (Strings.isEmpty(val)) {
            log.error("val为空");
            return false;
        } else {
            for (String a : Arrays.asList(array)) {
                if (Strings.equalsIgnoreCase(a, val)) {
                    return true;
                }
            }
            return false;
        }
    }

    public static String[] ShortText(String url) {

        String salt = "IB5.CN";                 //自定义生成MD5加密字符串前的混合KEY
        String[] chars = new String[]{          //要使用生成URL的字符
                "a", "b", "c", "d", "e", "f", "g", "h",
                "i", "j", "k", "l", "m", "n", "o", "p",
                "q", "r", "s", "t", "u", "v", "w", "x",
                "y", "z", "0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9", "A", "B", "C", "D",
                "E", "F", "G", "H", "I", "J", "K", "L",
                "M", "N", "O", "P", "Q", "R", "S", "T",
                "U", "V", "W", "X", "Y", "Z"
        };
        String hex = Lang.md5(salt + url);
        int hexLen = hex.length();
        int subHexLen = hexLen / 8;
        String[] ShortStr = new String[4];
        for (int i = 0; i < subHexLen; i++) {
            String outChars = "";
            int j = i + 1;
            String subHex = hex.substring(i * 8, j * 8);
            long idx = Long.valueOf("3FFFFFFF", 16) & Long.valueOf(subHex, 16);

            for (int k = 0; k < 6; k++) {
                int index = (int) (Long.valueOf("0000003D", 16) & idx);
                outChars += chars[index];
                idx = idx >> 5;
            }
            ShortStr[i] = outChars;
        }
        return ShortStr;
    }

    public static String[] ShortText(String url, String remark) {

        String salt = "IB5.CN";                 //自定义生成MD5加密字符串前的混合KEY
        String[] chars = new String[]{          //要使用生成URL的字符
                "a", "b", "c", "d", "e", "f", "g", "h",
                "i", "j", "k", "l", "m", "n", "o", "p",
                "q", "r", "s", "t", "u", "v", "w", "x",
                "y", "z", "0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9", "A", "B", "C", "D",
                "E", "F", "G", "H", "I", "J", "K", "L",
                "M", "N", "O", "P", "Q", "R", "S", "T",
                "U", "V", "W", "X", "Y", "Z"
        };
        String hex = Lang.md5(salt + url + remark);
        int hexLen = hex.length();
        int subHexLen = hexLen / 8;
        String[] ShortStr = new String[4];
        for (int i = 0; i < subHexLen; i++) {
            String outChars = "";
            int j = i + 1;
            String subHex = hex.substring(i * 8, j * 8);
            long idx = Long.valueOf("3FFFFFFF", 16) & Long.valueOf(subHex, 16);

            for (int k = 0; k < 6; k++) {
                int index = (int) (Long.valueOf("0000003D", 16) & idx);
                outChars += chars[index];
                idx = idx >> 5;
            }
            ShortStr[i] = outChars;
        }
        return ShortStr;
    }

    /**
     * 取URL标题
     *
     * @param url
     * @return
     */
    public static String getUrlTitle(String url) {
        if (Strings.isNotBlank(url) && Strings.isUrl(url)) {
            try {
                Document doc = Jsoup.connect(url).timeout(3000).get();
                return doc.title();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                return null;
            }
        } else
            return null;
    }

}
